local redis = require "libs/resty/redis"



local redis_util = {}


--用于执行redis命令
--redis命令说明 http://doc.redisfans.com/
redis_util.redis_cmd = function(server_name, cmd, ...)
    local start = ngx.now()
    if not (server_name and cmd) then
        nlog.warn("redis cmd error, shm_name=" .. tostring(server_name) .. ", cmd=" .. tostring(cmd))
        return nil, -1
    end
    local rc = redis_conf[server_name]
    local debug_str = "redis_name:" .. rc.host  .. " redis_cmd [" .. cmd
    for _, v in ipairs({...}) do
        debug_str = debug_str .. " " .. v
    end
    debug_str = debug_str .. "]"

    local red = redis:new()
    red:set_timeout(rc.connect_timeout)

    -- connect redis
    local connect_ok, connect_err = red:connect(rc.host, rc.port)
    if not connect_ok then
        nlog.error("connect redis failed! " .. debug_str .. " err=" .. connect_err)
        return nil, -2
    end
    if rc.password then
        --redis开启了授权认证
        local times, get_reused_times_err = red:get_reused_times()
        if not times then
            nlog.error("redis get_reused_times:" .. tostring(get_reused_times_err))
            return nil, -2
        elseif times == 0 then
            local res, auth_err = red:auth(rc.password)
            if not res then
                nlog.error("redis auth:" .. tostring(auth_err))
                return nil, -2
            end
        end
    end

    --exec cmd
    local ret, cmd_err = red[cmd](red, ...)
    if not ret then
        nlog.warn("exec cmd failed! ".. debug_str .. " err=" .. cmd_err)
        return nil, -4
    end

    local set_keepalive_ok, set_keepalive_err = red:set_keepalive(rc.keepalive.idle_time, rc.keepalive.pool_size)
    if not set_keepalive_ok then
        -- 保持连接失败并不会影响实际数据
        nlog.warn("set_keepalive failed!" .. tostring(set_keepalive_err))
        --return nil ,-5
    end

    local execute_time = ngx.now() - start
    nlog.info("[redis_cmd] execute_time: " .. tostring(execute_time) .. " debug_str: " .. tostring(debug_str))

    if ngx.null == ret or ret == "null" then
        return nil, 0
    end
    return ret, 0
end


redis_util.multi_exec = function(server_name, cmd_tb)
    -- local start = ngx.now()
    if not (server_name and cmd_tb) then
        nlog.warn("redis multi_cmd error, shm_name=" .. ", cmd_tb=" .. tostring(cmd_tb))
        return nil, -1
    end
    local rc = redis_conf[server_name]

    local debug_str = "redis_name:" .. rc.host  .. " redis_multi_cmd [" .. cjson.encode(cmd_tb)
    debug_str = debug_str .. "]"

    local red = redis:new()
    red:set_timeout(rc.connect_timeout)

    -- connect redis
    local connect_ok, connect_err = red:connect(rc.host, rc.port)
    if not connect_ok then
        nlog.error("connect redis failed! " .. debug_str .. " err=" .. connect_err)
        return nil, -2
    end
    if rc.password then
        --redis开启了授权认证
        local times, get_reused_times_err = red:get_reused_times()
        if not times then
            nlog.error("redis get_reused_times:" .. tostring(get_reused_times_err))
            return nil, -2
        elseif times == 0 then
            local res, auth_err = red:auth(rc.password)
            if not res then
                nlog.error("redis auth:" .. tostring(auth_err))
                return nil, -2
            end
        end
    end

    --exec cmd
    local ret, multi_err = red:multi()
    if "OK" ~= ret then
        nlog.error("red:multi error,ret:" .. (ret or "") .. " err:" .. (multi_err or ""))
        return nil, -1
    end
    for _, cmd_tmp in pairs(cmd_tb) do
        local red_err
        if #cmd_tmp == 1 then
            ret, red_err = red[cmd_tmp[1]](red)
        else
            ret, red_err = red[cmd_tmp[1]](red, unpack(cmd_tmp, 2))
        end

        if "QUEUED" ~= ret then
            nlog.error("queuend error, ret:" .. (ret or "") .. " err:" .. (red_err or ""))
            return nil, -1
        end
    end
    local exec_err
    ret, exec_err = red:exec()

    if not ret then
        nlog.warn("exec cmd failed! err:" .. (exec_err or "") .. " debug_str:" .. debug_str)
        return nil, -4
    end

    local set_keepalive_ok, set_keepalive_err = red:set_keepalive(rc.keepalive.idle_time, rc.keepalive.pool_size)
    if not set_keepalive_ok then
        -- 保持连接失败并不会影响实际数据
        nlog.warn("set_keepalive failed!" .. tostring(set_keepalive_err))
        --return nil ,-5
    end

    -- local elapsed_cmd = ngx.now() - start
    -- nlog.info("[redis_cmd] elapsed_cmd: " .. tostring(elapsed_cmd) .. " debug_str: " .. tostring(debug_str))

    if ngx.null == ret or ret == "null" then
        return nil, 0
    end
    return ret ,0
end


return redis_util
